/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.editor.ext;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Comparator;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.swing.text.JTextComponent;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import org.netbeans.editor.Analyzer;
import org.netbeans.editor.Acceptor;
import org.netbeans.editor.AcceptorFactory;
import org.netbeans.editor.Utilities;
import org.netbeans.editor.BaseDocument;
import org.netbeans.editor.FinderFactory;
import org.netbeans.editor.SyntaxSupport;
import org.netbeans.editor.GuardedException;
import org.netbeans.editor.SettingsUtil;
import org.netbeans.editor.LocaleSupport;
import org.netbeans.editor.Utilities;
/**
* Java completion support finder
*
* @author Miloslav Metelka
* @version 1.00
*/
public class JCQuery {
public JCQuery() {
}
public QueryResult getHelp(JTextComponent c) {
return getHelp(c, c.getCaret().getDot(), false);
}
/** Get the help according to the given position in the document.
* @param c text component
* @param pos position in the component's document. The context before this position
* is inspected to find the help info.
* @param sourceHelp find the help that can be used for opening the source code document.
* The source help is resolved in a slightly different way in some situations.
* e.g. open-source-action etc.
*/
public QueryResult getHelp(JTextComponent c, int pos, boolean sourceHelp) {
BaseDocument doc = (BaseDocument)c.getDocument();
QueryResult ret = null;
try {
JCTokenProcessor tp = parseToPosition(doc, pos);
switch (tp.getLastTokenID()) {
case JavaSyntax.BLOCK_COMMENT:
case JavaSyntax.LINE_COMMENT:
break;
default:
ret = resolveQuery(tp, doc, sourceHelp);
break;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
return ret;
}
/** Get the text that is normally filled into the text if enter is pressed. */
protected String getMainText(QueryResult queryResult, Object dataItem) {
String text = null;
if (dataItem instanceof JCPackage) {
text = ((JCPackage)dataItem).getLastName();
} else if (dataItem instanceof JCClass) {
text = ((JCClass)dataItem).getName();
int cdo = queryResult.getClassDisplayOffset();
if (cdo > 0 && cdo < text.length()) { // Only the last name for inner classes
text = text.substring(cdo);
}
} else if (dataItem instanceof JCField) {
text = ((JCField)dataItem).getName();
} else if (dataItem instanceof JCMethod) {
JCMethod mtd = (JCMethod)dataItem;
text = mtd.getName();
} else if (dataItem instanceof JCConstructor) {
text = ((JCConstructor)dataItem).getClazz().getName();
}
return text;
}
/** Get the text that is common to all the entries in the query-result */
String getCommonText(QueryResult queryResult, String prefix) {
List data = queryResult.getData();
int cnt = data.size();
int prefixLen = prefix.length();
String commonText = null;
for (int i = 0; i < cnt; i++) {
String mainText = getMainText(queryResult, data.get(i));
if (mainText != null && mainText.startsWith(prefix)) {
mainText = mainText.substring(prefixLen);
if (commonText == null) {
commonText = mainText;
}
// Get largest common part
int minLen = Math.min(mainText.length(), commonText.length());
int commonInd;
for (commonInd = 0; commonInd < minLen; commonInd++) {
if (mainText.charAt(commonInd) != commonText.charAt(commonInd)) {
break;
}
}
if (commonInd != 0) {
commonText = commonText.substring(0, commonInd);
} else {
return null; // no common text
}
}
}
return prefix + ((commonText != null) ? commonText : ""); // NOI18N
}
/** Update the text in response to pressing TAB key.
* @return whether the text was successfully updated
*/
public boolean updateCommonText(JTextComponent c, QueryResult queryResult) {
if (queryResult == null) {
return false;
}
BaseDocument doc = (BaseDocument)c.getDocument();
int startPos = queryResult.getSubstitutePosition();
int substLen = queryResult.getSubstituteLength();
try {
String prefix = doc.getText(startPos, substLen);
String commonText = getCommonText(queryResult, prefix);
if (commonText != null) {
doc.atomicLock();
try {
doc.remove(startPos, substLen);
doc.insertString(startPos, commonText, null);
} finally {
doc.atomicUnlock();
}
}
} catch (BadLocationException e) {
// no updating
}
return true;
}
/** Update the text in response to pressing ENTER.
* @return whether the text was successfully updated
*/
protected boolean updateText(JTextComponent c, List data, Object replacement,
QueryResult queryResult) {
if (queryResult == null) { // must be valid
return false;
}
BaseDocument doc = (BaseDocument)c.getDocument();
String text = null;
int selectionStartOffset = -1;
int selectionEndOffset = -1;
if (replacement instanceof JCPackage) {
text = ((JCPackage)replacement).getLastName();
} else if (replacement instanceof JCClass) {
text = ((JCClass)replacement).getName();
int cdo = queryResult.getClassDisplayOffset();
if (cdo > 0 && cdo < text.length()) { // Only the last name for inner classes
text = text.substring(cdo);
}
} else if (replacement instanceof JCField) {
text = ((JCField)replacement).getName();
} else if (replacement instanceof JCConstructor) {
JCConstructor mtd = (JCConstructor)replacement;
JCExpression substExp = queryResult.getSubstituteExp();
switch ((substExp != null) ? substExp.getID() : -1) {
case JCExpression.METHOD:
// no substitution
break;
case JCExpression.METHOD_OPEN:
JCParameter[] parms = mtd.getParameters();
if (parms.length == 0) {
text = ")"; // NOI18N
} else { // one or more parameters
int ind = substExp.getParameterCount();
boolean addSpace = SettingsUtil.getBoolean(Utilities.getKit(c).getClass(),
ExtSettings.FORMAT_COMMA_ADD_SPACE, true);
int sPos = queryResult.getSubstitutePosition();
try {
if (addSpace && (ind == 0 || (sPos > 0
&& Character.isWhitespace(doc.getText(sPos - 1, 1).charAt(0))))
) {
addSpace = false;
}
} catch (BadLocationException e) {
}
if (ind < parms.length) {
text = addSpace ? " " : ""; // NOI18N
selectionStartOffset = text.length();
text += parms[ind].getName();
selectionEndOffset = text.length();
}
}
break;
default:
text = getMainText(queryResult, replacement);
boolean addSpace = SettingsUtil.getBoolean(Utilities.getKit(c).getClass(),
ExtSettings.FORMAT_PARENTHESIS_ADD_SPACE, false);
if (addSpace) {
text += ' ';
}
text += '(';
parms = mtd.getParameters();
if (parms.length > 0) {
selectionStartOffset = text.length();
text += parms[0].getName();
selectionEndOffset = text.length();
} else {
text += ")"; // NOI18N
}
break;
}
} else if (replacement instanceof JCConstructor) {
text = ((JCConstructor)replacement).getClazz().getName();
}
if (text != null) {
// Update the text
doc.atomicLock();
try {
int startPos = queryResult.getSubstitutePosition();
doc.remove(startPos, queryResult.getSubstituteLength());
doc.insertString(startPos, text, null);
if (selectionStartOffset >= 0) {
c.select(startPos + selectionStartOffset, startPos + selectionEndOffset);
}
} catch (BadLocationException e) {
// Can't update
} finally {
doc.atomicUnlock();
}
}
return true;
}
/** Get the parsed expression that is at the top of the stack */
JCTokenProcessor parseToPosition(BaseDocument doc, int pos)
throws BadLocationException {
JavaSyntaxSupport sup = (JavaSyntaxSupport)doc.getSyntaxSupport();
int lastSep = sup.getLastCommandSeparator(pos);
JCTokenProcessor tp = new JCTokenProcessor();
sup.tokenizeText(tp, lastSep + 1, pos, true);
return tp;
}
/** Finds the fields, methods and the inner classes.
*/
static List findFieldsAndMethods(JCFinder finder, JCClass cls, String name,
boolean exactMatch, boolean staticOnly, boolean inspectOuterClasses) {
// Find inner classes
List ret = new ArrayList();
if (staticOnly) {
JCPackage pkg = finder.getExactPackage(cls.getPackageName());
if (pkg != null) {
ret = finder.findClasses(pkg, cls.getName() + '.' + name, false);
}
}
// Add fields
ret.addAll(finder.findFields(cls, name, exactMatch, staticOnly, inspectOuterClasses));
// Add methods
ret.addAll(finder.findMethods(cls, name, exactMatch, staticOnly, inspectOuterClasses));
return ret;
}
protected QueryResult resolveQuery(JCTokenProcessor tp, BaseDocument doc, boolean sourceHelp) {
JavaSyntaxSupport sup = (JavaSyntaxSupport)doc.getSyntaxSupport();
sup.refreshCompletion();
Context ctx = new Context(tp, sup, sourceHelp);
JCExpression exp = tp.getResultExp();
ctx.resolveExp(exp);
return ctx.queryResult;
}
public static class Context {
/** Token processor used for parsing the input */
private JCTokenProcessor tp;
/** Syntax support for the given document */
private JavaSyntaxSupport sup;
/** Whether get the source help or not. The source help has slightly
* different handling in some situations.
*/
private boolean sourceHelp;
/** If set to true true - find the type of the result expression.
* It's stored in the lastType variable or lastPkg if it's a package.
* The result variable is not populated.
* False means that the code completion output should be collected.
*/
private boolean findType;
/** Whether currently scanning either the package or the class name
* so the results should limit the search to the static fields and methods.
*/
private boolean staticOnly = true;
/** Last package found when scanning dot expression */
private JCPackage lastPkg;
/** Last type found when scanning dot expression */
private JCType lastType;
/** Result list when code completion output is generated */
private QueryResult queryResult;
/** Helper flag for recognizing constructors */
private boolean isConstructor;
public Context(JCTokenProcessor tp, JavaSyntaxSupport sup, boolean sourceHelp) {
this.tp = tp;
this.sup = sup;
this.sourceHelp = sourceHelp;
}
public void setFindType(boolean findType) {
this.findType = findType;
}
protected Object clone() {
return new Context(tp, sup, sourceHelp);
}
/* private List getBaseHelp(String baseName) {
if (sourceHelp) {
JCFinder finder = JCompletion.getFinder();
List res = finder.findPackages(baseName, false, false); // find all subpackages
if (res == null) {
res = new ArrayList();
}
if (baseName != null && baseName.length() > 0) {
res.addAll(finder.findClasses(null, baseName, false)); // add matching classes
}
return res;
}
return null;
}
private QueryResult getBaseHelpResult(String baseName, JCExpression exp) {
List res = getBaseHelp(baseName);
if (res != null && exp != null) {
return new QueryResult(res, formatName(baseName, true),
exp, exp.getTokenPosition(0), 0, 0);
}
return null;
}
*/
private String formatName(String name, boolean appendStar) {
return (name != null) ? (appendStar ? (name + '*') : name)
: (appendStar ? "*" : ""); // NOI18N
}
private String formatType(JCType type, boolean useFullName,
boolean appendDot, boolean appendStar) {
StringBuffer sb = new StringBuffer();
if (type != null) {
sb.append(type.format(useFullName));
}
if (appendDot) {
sb.append('.');
}
if (appendStar) {
sb.append('*');
}
return sb.toString();
}
private JCType resolveType(JCExpression exp) {
Context ctx = (Context)clone();
ctx.setFindType(true);
JCType typ = null;
if (ctx.resolveExp(exp)) {
typ = ctx.lastType;
}
return typ;
}
boolean resolveExp(JCExpression exp) {
boolean lastDot = false; // dot at the end of the whole expression?
JCFinder finder = JCompletion.getFinder();
boolean ok = true;
switch (exp.getID()) {
case JCExpression.DOT_OPEN: // Dot expression with the dot at the end
lastDot = true;
// let it flow to DOT
case JCExpression.DOT: // Dot expression
int parmCnt = exp.getParameterCount(); // Number of items in the dot exp
for (int i = 0; i < parmCnt && ok; i++) { // resolve all items in a dot exp
ok = resolveItem(exp.getParameter(i), (i == 0),
(!lastDot && i == parmCnt - 1)
);
}
if (ok && lastDot) { // Found either type or package help
// Need to process dot at the end of the expression
int tokenCntM1 = exp.getTokenCount() - 1;
int substPos = exp.getTokenPosition(tokenCntM1) + exp.getTokenLength(tokenCntM1);
if (lastType != null) { // Found type
JCClass cls;
if (lastType.getArrayDepth() == 0) { // Not array
cls = lastType.getClazz();
} else { // Array of some depth
cls = JCompletion.OBJECT_CLASS; // Use Object in this case
}
List res;
if (sourceHelp) {
res = new ArrayList();
res.add(lastType.getClazz());
} else { // not source-help
res = findFieldsAndMethods(finder, cls, "", false, staticOnly, false); // NOI18N
}
// Get all fields and methods of the cls
queryResult = new QueryResult(res, formatType(lastType, true, true, true),
exp, substPos, 0, cls.getName().length() + 1);
} else { // Found package (otherwise ok would be false)
String searchPkg = lastPkg.getName() + '.';
List res;
if (sourceHelp) {
res = new ArrayList();
res.add(lastPkg); // return only the package
} else {
res = finder.findPackages(searchPkg, false, false); // find all subpackages
res.addAll(Arrays.asList(lastPkg.getClasses())); // package classes
}
queryResult = new QueryResult(res, searchPkg + '*',
exp, substPos, 0, 0);
}
}
break;
case JCExpression.NEW: // 'new' keyword
List res = finder.findClasses(null, "", false); // Find all classes by name // NOI18N
queryResult = new QueryResult(res, "*", exp, tp.getLastPosition(), 0, 0); // NOI18N
break;
default: // The rest of the situations is resolved as a singleton item
ok = resolveItem(exp, true, true);
break;
}
return ok;
}
/** Resolve one item from the expression connected by dots.
* @param item expression item to resolve
* @param first whether this expression is the first one in a dot expression
* @param last whether this expression is the last one in a dot expression
*/
boolean resolveItem(JCExpression item, boolean first, boolean last) {
boolean cont = true; // whether parsing should continue or not
boolean methodOpen = false; // helper flag for unclosed methods
JCFinder finder = JCompletion.getFinder();
switch (item.getID()) {
case JCExpression.CONSTANT: // Constant item
if (first) {
lastType = item.getType(); // Get the constant type
} else { // Not the first item in a dot exp
cont = false; // impossible to have constant inside the expression
}
break;
case JCExpression.VARIABLE: // Variable or special keywords
if (item.getTokenID(0) == JavaSyntax.KEYWORD) { // special keywords
switch (item.getTokenHelperID(0)) {
case JavaKeywords.THIS: // 'this' keyword
if (first) { // first item in expression
JCClass cls = sup.getClass(item.getTokenPosition(0));
if (cls != null) {
lastType = JCompletion.getType(cls, 0);
staticOnly = false;
}
} else { // 'something.this'
staticOnly = false;
}
break;
case JavaKeywords.SUPER: // 'super' keyword
if (first) { // only allowed as the first item
JCClass cls = sup.getClass(item.getTokenPosition(0));
if (cls != null) {
cls = finder.getExactClass(cls.getFullName());
if (cls != null) {
cls = cls.getSuperclass();
if (cls != null) {
lastType = JCompletion.getType(cls, 0);
staticOnly = false;
}
}
}
} else {
cont = false;
}
break;
case JavaKeywords.CLASS: // 'class' keyword
if (!first) {
lastType = JCompletion.CLASS_TYPE;
} else {
cont = false;
}
break;
}
} else { // regular constant
String var = item.getTokenText(0);
int varPos = item.getTokenPosition(0);
if (first) { // try to find variable for the first item
if (last && !findType) { // both first and last item
List res = new ArrayList();
JCClass cls = sup.getClass(varPos); // get document class
if (cls != null) {
res.addAll(findFieldsAndMethods(finder, cls, var, false,
sup.isStaticBlock(varPos), true));
}
if (var.length() > 0 || !sourceHelp) {
res.addAll(finder.findPackages(var, false, false)); // add matching packages
if (var.length() > 0) { // if at least one char
res.addAll(finder.findClasses(null, var, false)); // add matching classes
}
}
queryResult = new QueryResult(res, var + '*', item, 0);
} else { // not last item or finding type
lastType = (JCType)sup.findType(var, varPos);
if (lastType != null) { // variable found
staticOnly = false;
} else { // no variable found
lastPkg = finder.getExactPackage(var); // try package
if (lastPkg == null) { // not package, let's try class name
JCClass cls = sup.getClassFromName(var, true);
if (cls != null) {
lastType = JCompletion.getType(cls, 0);
} else { // class not found
cont = false;
}
}
}
}
} else { // not the first item
if (lastType != null) { // last was type
if (findType || !last) {
boolean inner = false;
int ad = lastType.getArrayDepth();
if (staticOnly && ad == 0) { // can be inner class
JCClass cls = finder.getExactClass(lastType.getClazz().getFullName() + "." + var); // NOI18N
if (cls != null) {
lastType = JCompletion.getType(cls, 0);
inner = true;
}
}
if (!inner) { // not inner class name
if (ad == 0) { // zero array depth
List fldList = finder.findFields(lastType.getClazz(), var, true, staticOnly, false);
if (fldList.size() > 0) { // match found
JCField fld = (JCField)fldList.get(0);
lastType = fld.getType();
staticOnly = false;
} else { // no match found
lastType = null;
cont = false;
}
} else { // array depth > 0 but no array dereference
cont = false;
}
}
} else { // last and searching for completion output
JCClass cls = lastType.getClazz();
queryResult = new QueryResult(
findFieldsAndMethods(finder, cls, var, false, staticOnly, false),
lastType.format(false) + '.' + var + '*',
item,
cls.getName().length() + 1);
}
} else { // currently package
String searchName = lastPkg.getName() + '.' + var;
if (findType || !last) {
lastPkg = finder.getExactPackage(searchName);
if (lastPkg == null) { // package doesn't exist
JCClass cls = finder.getExactClass(searchName);
if (cls != null) {
lastType = JCompletion.getType(cls, 0);
} else {
lastType = null;
cont = false;
}
}
} else { // last and searching for completion output
if (last) { // get all matching fields/methods/packages
String searchPkg = lastPkg.getName() + '.' + var;
List res = finder.findPackages(searchPkg, false, false); // find matching subpackages
res.addAll(finder.findClasses(lastPkg, var, false)); // matching classes
queryResult = new QueryResult(res, searchPkg + '*', item, 0);
}
}
}
}
}
break;
case JCExpression.ARRAY:
cont = resolveItem(item.getParameter(0), first, false);
if (cont) {
cont = false;
if (lastType != null) { // must be type
if (item.getParameterCount() == 2) { // index in array follows
JCType arrayType = resolveType(item.getParameter(1));
if (arrayType != null && arrayType.equals(JCompletion.INT_TYPE)) {
lastType = JCompletion.getType(lastType.getClazz(),
Math.max(lastType.getArrayDepth() - 1, 0));
cont = true;
}
} else { // no index, increase array depth
lastType = JCompletion.getType(lastType.getClazz(),
lastType.getArrayDepth() + 1);
cont = true;
}
}
}
break;
case JCExpression.INSTANCEOF:
lastType = JCompletion.BOOLEAN_TYPE;
break;
case JCExpression.OPERATOR:
switch (item.getTokenHelperID(0)) {
case JavaSyntax.EQ: // Assignment operators
case JavaSyntax.PLUS_EQ:
case JavaSyntax.MINUS_EQ:
case JavaSyntax.MUL_EQ:
case JavaSyntax.DIV_EQ:
case JavaSyntax.AND_EQ:
case JavaSyntax.OR_EQ:
case JavaSyntax.XOR_EQ:
case JavaSyntax.MOD_EQ:
case JavaSyntax.LLE:
case JavaSyntax.GGE:
case JavaSyntax.GGGE:
if (item.getParameterCount() > 0) {
lastType = resolveType(item.getParameter(0));
}
break;
case JavaSyntax.LT: // Binary, result is boolean
case JavaSyntax.GT:
case JavaSyntax.LE:
case JavaSyntax.GE:
case JavaSyntax.EQ_EQ:
case JavaSyntax.NOT_EQ:
case JavaSyntax.AND_AND: // Binary, result is boolean
case JavaSyntax.OR_OR:
lastType = JCompletion.BOOLEAN_TYPE;
break;
case JavaSyntax.LLT: // Always binary
case JavaSyntax.GGT:
case JavaSyntax.GGGT:
case JavaSyntax.MUL:
case JavaSyntax.DIV:
case JavaSyntax.AND:
case JavaSyntax.OR:
case JavaSyntax.XOR:
case JavaSyntax.MOD:
case JavaSyntax.PLUS:
case JavaSyntax.MINUS:
switch (item.getParameterCount()) {
case 2:
JCType typ1 = resolveType(item.getParameter(0));
JCType typ2 = resolveType(item.getParameter(1));
if (typ1 != null && typ2 != null
&& typ1.getArrayDepth() == 0
&& typ2.getArrayDepth() == 0
&& JCompletion.isPrimitiveClass(typ1.getClazz())
&& JCompletion.isPrimitiveClass(typ2.getClazz())
) {
lastType = JCUtilities.getCommonType(typ1, typ2);
}
break;
case 1: // get the only one parameter
JCType typ = resolveType(item.getParameter(0));
if (typ != null && JCompletion.isPrimitiveClass(typ.getClazz())) {
lastType = typ;
}
break;
}
break;
case JavaSyntax.COLON:
switch (item.getParameterCount()) {
case 2:
JCType typ1 = resolveType(item.getParameter(0));
JCType typ2 = resolveType(item.getParameter(1));
if (typ1 != null && typ2 != null) {
lastType = JCUtilities.getCommonType(typ1, typ2);
}
break;
case 1:
lastType = resolveType(item.getParameter(0));
break;
}
break;
case JavaSyntax.QUESTION:
if (item.getParameterCount() >= 2) {
lastType = resolveType(item.getParameter(1)); // should be colon
}
break;
}
break;
case JCExpression.UNARY_OPERATOR:
if (item.getParameterCount() > 0) {
lastType = resolveType(item.getParameter(0));
}
break;
case JCExpression.CONVERSION:
lastType = resolveType(item.getParameter(0));
staticOnly = false;
break;
case JCExpression.PARENTHESIS:
cont = resolveItem(item.getParameter(0), first, last);
break;
case JCExpression.CONSTRUCTOR: // constructor can be part of a DOT expression
isConstructor = true;
cont = resolveExp(item.getParameter(0));
staticOnly = false;
break;
case JCExpression.METHOD_OPEN: // Unclosed method
methodOpen = true;
// let it flow to method
case JCExpression.METHOD: // Closed method
String mtdName = item.getTokenText(0);
if (isConstructor) { // Help for the constructor
JCClass cls = null;
if (first) {
cls = sup.getClassFromName(mtdName, true);
} else { // not first
if (lastPkg != null) { // valid package
cls = JCUtilities.getExactClass(finder, mtdName, lastPkg.getName());
} else if (lastType != null) { // valid type -> will be inner clas
cls = JCUtilities.getExactClass(finder, mtdName,
lastType.getClazz().getFullName());
}
}
if (cls != null) {
lastType = JCompletion.getType(cls, 0);
List ctrList = JCUtilities.getConstructors(cls);
String parmStr = "*"; // NOI18N
List typeList = getTypeList(item);
List filtered = JCUtilities.filterMethods(ctrList, typeList, methodOpen);
if (filtered.size() > 0) {
ctrList = filtered;
parmStr = formatTypeList(typeList, methodOpen);
}
queryResult = new QueryResult(ctrList,
mtdName + '(' + parmStr + ')',
item, tp.getLastPosition(), 0, 0);
}
} else {
// Help for the method
if (first) {
JCClass cls = sup.getClass(item.getTokenPosition(0));
if (cls != null) {
lastType = JCompletion.getType(cls, 0);
}
}
if (lastType != null) {
List mtdList = finder.findMethods(lastType.getClazz(), mtdName, true, false, first);
String parmStr = "*"; // NOI18N
List typeList = getTypeList(item);
List filtered = JCUtilities.filterMethods(mtdList, typeList, methodOpen);
if (filtered.size() > 0) {
mtdList = filtered;
parmStr = formatTypeList(typeList, methodOpen);
}
if (mtdList.size() > 0) {
if (last && !findType) {
queryResult = new QueryResult(mtdList,
lastType.getClazz().toString() + '.' + mtdName + '(' + parmStr + ')',
item, tp.getLastPosition(), 0, 0);
} else {
if (mtdList.size() > 0) {
lastType = ((JCMethod)mtdList.get(0)).getReturnType();
staticOnly = false;
}
}
} else {
lastType = null; // no method found
cont = false;
}
} else { // package.method() is invalid
lastPkg = null;
cont = false;
}
}
break;
}
if (lastType == null && lastPkg == null) { // !!! shouldn't be necessary
cont = false;
}
return cont;
}
private List getTypeList(JCExpression item) {
int parmCnt = item.getParameterCount();
ArrayList typeList = new ArrayList();
if (parmCnt > 0) { // will try to filter by parameters
boolean methodOpen = (item.getID() == JCExpression.METHOD_OPEN);
for (int i = 0; i < parmCnt; i++) {
JCExpression parm = item.getParameter(i);
JCType typ = resolveType(parm);
typeList.add(typ);
}
}
return typeList;
}
}
private static String formatTypeList(List typeList, boolean methodOpen) {
StringBuffer sb = new StringBuffer();
if (typeList.size() > 0) {
int cntM1 = typeList.size() - 1;
for (int i = 0; i <= cntM1; i++) {
JCType t = (JCType)typeList.get(i);
if (t != null) {
sb.append(t.format(false));
} else {
sb.append('?');
}
if (i < cntM1) {
sb.append(", "); // NOI18N
}
}
if (methodOpen) {
sb.append(", *"); // NOI18N
}
} else { // no parameters
if (methodOpen) {
sb.append("*"); // NOI18N
}
}
return sb.toString();
}
public static class QueryResult {
private List data;
private String title;
/** First offset in the name of the (inner) class
* to be displayed. It's used to display the inner classes
* of the main class to exclude the initial part of the name.
*/
private int classDisplayOffset;
/** Expression to substitute */
private JCExpression substituteExp;
/** Starting position of the text to substitute */
private int substitutePosition;
/** Length of the text to substitute */
private int substituteLength;
QueryResult(List data, String title, JCExpression substituteExp, int classDisplayOffset) {
this(data, title, substituteExp, substituteExp.getTokenPosition(0),
substituteExp.getTokenLength(0), classDisplayOffset);
}
QueryResult(List data, String title, JCExpression substituteExp, int substitutePosition,
int substituteLength, int classDisplayOffset) {
this.data = data;
this.title = title;
this.substituteExp = substituteExp;
this.substitutePosition = substitutePosition;
this.substituteLength = substituteLength;
this.classDisplayOffset = classDisplayOffset;
}
public final List getData() {
return data;
}
public final String getTitle() {
return title;
}
public final int getClassDisplayOffset() {
return classDisplayOffset;
}
public final int getSubstitutePosition() {
return substitutePosition;
}
public final int getSubstituteLength() {
return substituteLength;
}
public final JCExpression getSubstituteExp() {
return substituteExp;
}
}
}
/*
* Log
* 30 Gandalf-post-FCS1.28.1.0 3/8/00 Miloslav Metelka
* 29 Gandalf 1.28 2/15/00 Miloslav Metelka parenthesis instead of
* curly braces
* 28 Gandalf 1.27 1/15/00 Miloslav Metelka #5270
* 27 Gandalf 1.26 1/13/00 Miloslav Metelka Localization
* 26 Gandalf 1.25 1/11/00 Miloslav Metelka
* 25 Gandalf 1.24 1/10/00 Miloslav Metelka
* 24 Gandalf 1.23 1/4/00 Miloslav Metelka
* 23 Gandalf 1.22 12/28/99 Miloslav Metelka
* 22 Gandalf 1.21 11/24/99 Miloslav Metelka
* 21 Gandalf 1.20 11/14/99 Miloslav Metelka
* 20 Gandalf 1.19 11/10/99 Miloslav Metelka
* 19 Gandalf 1.18 11/9/99 Miloslav Metelka
* 18 Gandalf 1.17 11/8/99 Miloslav Metelka
* 17 Gandalf 1.16 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 16 Gandalf 1.15 10/10/99 Miloslav Metelka
* 15 Gandalf 1.14 10/4/99 Miloslav Metelka
* 14 Gandalf 1.13 9/30/99 Miloslav Metelka
* 13 Gandalf 1.12 9/15/99 Miloslav Metelka
* 12 Gandalf 1.11 9/10/99 Miloslav Metelka
* 11 Gandalf 1.10 8/27/99 Miloslav Metelka
* 10 Gandalf 1.9 8/18/99 Miloslav Metelka
* 9 Gandalf 1.8 8/18/99 Miloslav Metelka
* 8 Gandalf 1.7 7/30/99 Miloslav Metelka
* 7 Gandalf 1.6 7/29/99 Miloslav Metelka
* 6 Gandalf 1.5 7/22/99 Miloslav Metelka
* 5 Gandalf 1.4 7/21/99 Miloslav Metelka
* 4 Gandalf 1.3 7/21/99 Miloslav Metelka
* 3 Gandalf 1.2 7/20/99 Miloslav Metelka
* 2 Gandalf 1.1 6/10/99 Miloslav Metelka
* 1 Gandalf 1.0 6/8/99 Miloslav Metelka
* $
*/